﻿///////////////////////////////////////////////////////////////
//                                                           //
// Code from Arcanea Project.                                //
//                                                           //
// Please include this license part to every reproduction    //
//   of code.                                                //
//                                                           //
// This code is under Ms-RL license                          //
//                                                           //
// Please read futher information about the license,         //
//   the project (news and updates) and the                  //
//   contributors on the address :                           //
//     http://www.codeplex.com/Arcanea/                      //
//                                                           //
///////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using Arcanea.Mediator.XmlClasses;
using Arcanea.Mediator.BinaryClasses;
using Arcanea.Mediator.FullClasses;

namespace Arcanea.Mediator.Toolbox
{
    /// <summary>
    /// Classe boite a outil afin de gerer les FullPackets.
    /// </summary>
    public class FullToolbox
    {
        public IList<XmlPacket> allPackets = null;
        private readonly string filePath = "Packets.xml";

        #region Singleton

        private static FullToolbox instance = null;
        public static FullToolbox Instance
        {
            get
            {
                if (instance == null)
                    instance = new FullToolbox();
                return instance;
            }
        }

        private FullToolbox()
        {
            allPackets = XMLToolbox.XmlListPacketLoading(filePath);
            if (!CheckAllPackets())
                throw new ArgumentException("Unable to parse all types");
        }

        #endregion

        /// <summary>
        /// Enveloppe un BinPacket dans un FullPacket.
        /// </summary>
        /// <param name="packet">paquet simple a envelopper</param>
        /// <returns>Le FullPacket fraichement cree</returns>
        public FullPacket PackBinPacketToFullPacket(BinPacket packet)
        {
            if (packet.Id < 0 || packet.Id > allPackets.Count)
                return null;

            return new FullPacket(packet, allPackets[packet.Id]);
        }

        /// <summary>
        /// Cree un FullPacket a partir de son nom.
        /// Retrouve son 'schema' dans la base des paquets
        /// </summary>
        /// <param name="xmlPacketName">Nom du paquet</param>
        /// <returns>Le FullPacket cree</returns>
        public FullPacket CreateFullPacket(string xmlPacketName)
        {
            int index = IndexOf(xmlPacketName.ToLower());
            XmlPacket xmlP = allPackets[index];

            BinPacket binP = new BinPacket();
            binP.values = new object[xmlP.Fields.Count];

            return new FullPacket(binP, xmlP);

        }

        /// <summary>
        /// Retourne l index du FullPacket dans sa liste de definition
        /// </summary>
        /// <param name="xmlPacketName">Nom du paquet</param>
        /// <returns>index trouve sinon leve une exception</returns>
        public int IndexOf(string xmlPacketName)
        {
            for (int i = 0; i < allPackets.Count; i++)
                if (allPackets[i].Name == xmlPacketName)
                    return i;

            throw new Exception("Paquet XML non trouvable : " + xmlPacketName);
        }

        private bool CheckAllPackets()
        {

            foreach (XmlPacket p in allPackets)
                foreach (XmlField f in p.Fields)
                    if (!CheckType(f.SystemType, allPackets))
                        return false;

            return true;
        }

        private bool CheckType(string type, IList<XmlPacket> allPackets)
        {
            Type t = Type.GetType(type, false);
            if (t != null)
                return true;

            for (int i = 0; i < allPackets.Count; i++)
            {
                if (type == allPackets[i].Name)
                    return true;
            }

            return false;
        }
    }
}
